/**
 * Copyright (c) 广州点步信息科技有限公司 2016-2017, wjun_java@163.com.
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * http://www.dbumama.com
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.dbumama.market.web.core.interceptor;

import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.dbumama.market.model.BuyerUser;
import com.dbumama.market.service.api.user.UserService;
import com.dbumama.market.service.constants.Constants;
import com.dbumama.market.web.core.utils.IpKit;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.core.JFinal;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.weixin.sdk.api.ApiResult;
import com.weixin.sdk.kit.ParaMap;
import com.weixin.sdk.kit.WxSdkPropKit;

/**
 * @author wangjun
 */
public class MobileSessionInterceptor extends AbstractMobileInterceptor {

    public Logger logger = Logger.getLogger(getClass());

    final static String SNSSCOPE_BASE = "snsapi_base";

    final static String SNSSCOPE_USERINFO = "snsapi_userinfo";

    /**
     * 微信oath2授权地址;通过该地址拿到用户授权code码
     **/
    static final String oauth_url = "https://open.weixin.qq.com/connect/oauth2/authorize";

    /**
     * 根据code获取openId以及access_token
     **/
    static final String oauth_url_code = "https://api.weixin.qq.com/sns/oauth2/access_token";

    /**
     * 刷新网页授权token，获取更长时效的token值（可选）,该接口拿到的值可以延长用户授权
     **/
    static final String oauth_url_refreshtoken = "https://api.weixin.qq.com/sns/oauth2/refresh_token";

    /**
     * 授权后获取用户信息 无需用户关注公众号 scope=snsapi_userinfo
     **/
    static final String oauth_url_getuserinfo = "https://api.weixin.qq.com/sns/userinfo";

    /**
     * 检验授权凭证（access_token）是否有效
     */
    static final String oauth_url_token_check = "https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID";

    UserService userService = (UserService) ctx.getBean("userService");

    /* (non-Javadoc)
     * @see com.dbumama.market.web.core.interceptor.AbstractMobileInterceptor#doIntercept(com.jfinal.aop.Invocation)
     */
    @Override
    public void doIntercept(Invocation ai) {
        BuyerUser buyerUser = userService.findById(1l);
        ai.getController().getSession().setAttribute(Constants.BUYER_USER_IN_SESSION, buyerUser);
        ai.invoke();
    }

    protected void checkSession(Invocation ai) {
        Controller controller = ai.getController();
        HttpSession session = controller.getSession();

        //1，检查本地服务器用户session
        //2，检查微信服务器用户授权是否过期
        if (session.getAttribute(Constants.BUYER_USER_IN_SESSION) == null) {
            try {
                //去授权，默认都采用base方式
                gotoOauth(controller, SNSSCOPE_USERINFO);
            } catch (IOException e) {
                throw new RuntimeException(e.getMessage());
            }
        } else {
            ai.invoke();
        }
    }

    @SuppressWarnings("deprecation")
    protected static String getRedirectUrl(HttpServletRequest request, String rUrl) {
        String mainUrl = "http://" + request.getServerName();//微信只支持80端口
        return mainUrl + "/callback" + "?rUrl=" + (StringUtils.isNotBlank(rUrl) ? URLEncoder.encode(rUrl) : "");
    }

    /**
     * 1、以snsapi_base为scope发起的网页授权，是用来获取进入页面的用户的openid的，
     * 并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页（往往是业务页面）
     * 2、以snsapi_userinfo为scope发起的网页授权，是用来获取用户的基本信息的。
     * 但这种授权需要用户手动同意，并且由于用户同意过，所以无须关注，就可在授权后获取该用户的基本信息。
     * 3、用户管理类接口中的“获取用户基本信息接口”，是在用户和公众号产生消息交互或关注后事件推送后，才能根据用户OpenID来获取用户基本信息。
     * 这个接口，包括其他微信接口，都是需要该用户（即openid）关注了公众号后，才能调用成功的。
     * https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE&component_appid=component_appid#wechat_redirect
     *
     * @param controller
     * @param scope
     * @throws IOException
     */
    @SuppressWarnings("deprecation")
    private void gotoOauth(Controller controller, String scope) throws IOException {
        String mainUrl = "http://" + controller.getRequest().getServerName();
        String rurl = mainUrl + controller.getRequest().getServletPath();
        if (controller.getRequest().getQueryString() != null) {
            rurl += "?" + controller.getRequest().getQueryString();
        }
        logger.debug("=======================rurl:" + rurl);
        String callbackUrl = getRedirectUrl(controller.getRequest(), rurl);
        String _url = oauth_url + "?appid=" + WxSdkPropKit.get("wx_app_id") + "&redirect_uri=" + URLEncoder.encode(callbackUrl) + "&response_type=code&scope=" + scope + "&state=STATE#wechat_redirect";
        controller.redirect(_url);
    }

    @SuppressWarnings("deprecation")
    final static String decode(String s) {
        return StrKit.isBlank(s) ? null : URLDecoder.decode(s);
    }

    public Map<String, String> genOauthMap(String code, String rUrl) {
        Map<String, String> props = new HashMap<String, String>();
        props.put("code", code);
        props.put("appid", WxSdkPropKit.get("wx_app_id"));
        props.put("secret", WxSdkPropKit.get("wx_app_secret"));
        props.put("redirect_uri", rUrl);
        props.put("view", "web");
        props.put("grant_type", "authorization_code");
        return props;
    }

}
